#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

#include "Debug.h"

#define  SEM_KEY  12345

union semun {
    int val;                /* value for SETVAL */
    struct semid_ds *buf;   /* buffer for IPC_STAT, IPC_SET */
    unsigned short *array;  /* array for GETALL, SETALL */
    struct seminfo *__buf;  /* buffer for IPC_INFO */
};

int semproc_getid()
{
    static int s_semid = -1;
    if(s_semid < 0)
    {
        // system("touch /tmp/sem");
        // int key = ftok("/tmp/sem", 0x660);
        int key = SEM_KEY;   
        int semid = semget(key, 1, 0666);
        if(semid < 0)
        {
            Safe_Printf("not exist sem key=%d. create sem", key);
            semid = semget(key, 1, IPC_CREAT|0666);
            // init
            union semun arg;
            arg.val = 1;
            // if semid is -1, ret is -1
            // use 0 sem group
            int ret = semctl(semid, 0, SETVAL, arg);
            Safe_Printf("set arg[0].val=%d, ret=%d", arg.val, ret);
        }
        if(semid < 0)
        {
            Safe_Printf("create semget error, semid=%d", semid);
            return -1;
        }
        Safe_Printf("init sem ok. key=%d, semid=%d", key, semid);
        s_semid = semid;
    }
    return s_semid;
}

int semproc_getval()
{
    int semid = semproc_getid();
    union semun arg;
    int ret0 = semctl(semid, 0, GETVAL, arg);
    Safe_Printf("val=%d", ret0);
    return ret0;
}

// P lock.  del  sem
int semproc_lock()
{
    int semid = semproc_getid();
    int semnum = 0;
//    Safe_Printf("lock...") ;
    struct sembuf sops={semnum,-1, SEM_UNDO};
    int flag = (semop(semid, &sops, 1));
//    Safe_Printf("lock ret=%d", flag);
    return flag;
}

// V unlock.  add  sem
int semproc_unlock()
{
    int semid = semproc_getid();
    int semnum = 0;
//    Safe_Printf("V...") ;
    struct sembuf sops={semnum,+1, SEM_UNDO};
    int flag = (semop(semid, &sops, 1));
//    Safe_Printf("V ret=%d", flag);
    return flag;
}

int semproc_test()
{
    semproc_getval();
    // P
    while(1){
        int flag = semproc_lock();
        if ( flag < 0 )
        {
            return -1 ;
        }
    }

    // V
    while(1){
        int flag = semproc_unlock();
        if (flag < 0)
        {
            return -1;
        }
    }

//    if ( argc >1 ) semctl(semid,0,IPC_RMID,arg);
    return 0 ;
}




